# _*_ coding: utf-8 _*_
# .@FileName:NeckSrc
# .@Data....:2025-04-05 : 21 : 33
# .@Aurhor..:LiuJingYu
"""
launch:
from __future__ import unicode_literals, print_function
import maya.cmds as mc
"""
import maya.cmds as cmds


def get_hierarchical_bone_chain(root_bone):
    """递归获取按层级排序的骨骼链"""
    bone_chain = [root_bone]
    children = cmds.listRelatives(root_bone, children=True, type='joint')
    if children:
        for child in children:
            bone_chain.extend(get_hierarchical_bone_chain(child))
    return bone_chain


def create_and_match_objects(bone_chain, loc_pelvis_name='loc_m_NeckIKTwist_001',
                             loc_cheat_name='loc_m_HeadIKTwist_001',
                             jnt_pelvis_name='Jnt_m_NeckIK_001', jnt_cheat_name='Jnt_m_HeadIK_001',
                             zero_pelvis_name='zero_m_NeckIKTwist_001', zero_cheat_name='zero_m_HeadIKTwist_001'):
    # 创建定位器和骨骼
    loc_pelvis = cmds.spaceLocator(name=loc_pelvis_name)[0]
    loc_cheat = cmds.spaceLocator(name=loc_cheat_name)[0]
    cmds.select(cl=True)
    jnt_pelvis = cmds.joint(name=jnt_pelvis_name)
    cmds.select(cl=True)
    jnt_cheat = cmds.joint(name=jnt_cheat_name)
    cmds.select(cl=True)

    # 打组
    zero_pelvis = cmds.group(loc_pelvis, name=zero_pelvis_name)
    zero_cheat = cmds.group(loc_cheat, name=zero_cheat_name)

    first_bone = bone_chain[0]
    last_bone = bone_chain[-1]
    second_last_bone = bone_chain[-2] if len(bone_chain) > 1 else first_bone

    # 匹配位移和旋转
    cmds.matchTransform(zero_pelvis, first_bone, pos=True, rot=True)
    cmds.matchTransform(zero_cheat, last_bone, pos=True, rot=True)
    cmds.matchTransform(jnt_pelvis, first_bone, pos=True, rot=True)
    cmds.matchTransform(jnt_cheat, second_last_bone, pos=True, rot=True)

    return loc_pelvis, loc_cheat, jnt_pelvis, jnt_cheat, zero_pelvis, zero_cheat


# 获取所选的骨骼，这里假设选择的是各骨骼链的根骨骼
selected_root_bones = cmds.ls(selection=True, type='joint')

if not selected_root_bones:
    cmds.warning("请选择至少一个骨骼链的根骨骼。")
else:
    for root_bone in selected_root_bones:
        # 获取当前骨骼链的所有骨骼（按层级排序）
        bone_chain = get_hierarchical_bone_chain(root_bone)

        # 获取每个骨骼的位置
        points = []
        for bone in bone_chain:
            position = cmds.xform(bone, query=True, translation=True, worldSpace=True)
            points.append(position)

        # 处理第一个选择的骨骼名称
        first_bone_name = bone_chain[0]
        new_name = first_bone_name.replace("Jnt_", "").replace("_001", "")
        new_name = f"Cv_{new_name}_IK_001"

        # 根据骨骼位置创建曲线，并指定曲线名称
        curve = cmds.curve(point=points, name=new_name)
        print(f"已为骨骼链 {root_bone} 创建曲线: {curve}")

        # 选择第一个骨骼、最后一个骨骼和曲线
        first_bone = bone_chain[0]
        last_bone = bone_chain[-1]
        cmds.select([first_bone, last_bone, curve])

        # 创建 Ik Spine，添加 -ccv false 和 -pcv false 参数
        result = cmds.ikHandle(
            solver='ikSplineSolver',
            curve=curve,
            startJoint=first_bone,
            endEffector=last_bone,
            ccv=False,
            pcv=False
        )
        if len(result) == 2:
            ik_handle, effector = result
            curve_info = None
        else:
            ik_handle, effector, curve_info = result

        # 处理曲线名称，去掉 "Cv_"
        curve_name_without_prefix = curve.replace("Cv_", "")

        # 生成新的 Ik 手柄名称
        new_ik_handle_name = f"ikHandle_{curve_name_without_prefix}"

        # 重命名 Ik 手柄
        ik_handle = cmds.rename(ik_handle, new_ik_handle_name)

        print(f"已为曲线 {curve} 创建并命名 Ik Spine 手柄: {ik_handle}")

        # 检查 rigNodesLocal 组是否存在，不存在则创建
        if not cmds.objExists('rigNodesLocal'):
            cmds.group(name='rigNodesLocal', empty=True)

        # 将 ik 手柄放入 rigNodesLocal 组
        cmds.parent(ik_handle, 'rigNodesLocal')

        # 调用函数创建并匹配对象
        loc_pelvis, loc_cheat, jnt_pelvis, jnt_cheat, zero_pelvis, zero_cheat = create_and_match_objects(bone_chain)

        # 选择 ik 手柄并进行 Advanced Twist Controls 设置
        cmds.select(ik_handle)
        cmds.setAttr(f"{ik_handle}.dTwistControlEnable", 1)
        cmds.setAttr(f"{ik_handle}.dWorldUpType", 4)
        cmds.connectAttr(f"{loc_pelvis}.worldMatrix[0]", f"{ik_handle}.dWorldUpMatrix", force=True)
        cmds.connectAttr(f"{loc_cheat}.worldMatrix[0]", f"{ik_handle}.dWorldUpMatrixEnd", force=True)

        # 使用 jnt_pelvis 和 jnt_cheat 对 curve 进行蒙皮
        cmds.skinCluster(jnt_pelvis, jnt_cheat, curve)
